#include "tester.h"
#include "kernel/astralapi.h"
#define ROUND_EXP (5)
extern struct Test _start_tester;
extern struct Test _end_tester;


static unsigned round;
static struct AstralTickTimer timer;


static void report_test()
{
    char * fmt1 = "%10s %10s %10s %10s %10s\n";
    char * fmt2 = "%10s %10d %10d %10d %10d\n";
    kprint("\n\n=============report==============\n");
    kprint(fmt1, "name", "pass", "max", "min", "total");

    boolean allpass = True;
    for (Test t = &_start_tester; t < &_end_tester; t++)
    {
        kprint(fmt2, t->tname, t->passed, t->ticks_max, t->ticks_min, t->ticks_tot);
        if(t->passed != ROUND_EXP)
        {
            allpass = False;
        }
    }
    if(round != ROUND_EXP)
    {
        allpass = False;
    }
    kprint("Auto test %d round done!\n\n", round);
    if(!allpass)
    {
        kprint("Auto Test Failed!!!\n");
    }
    else
    {
        kprint("Auto Test Passed!!!\n");
    }
}

static void test_timeout(object arg)
{
    kerror("Round[%03d] Test timeout!\n", round);
    kprint("Test not done in %d ticks\n",CAST_AS(int, arg));
    report_test();
}


void autotest(int argc, char *argv[])
{

    AstralTaskPool create_task_pool(const char *name, int nr_thread, int prio);
    AstralTaskPool pool = create_task_pool("hello", 5, 19);



    create_ttimer(&timer, 1000, test_timeout, CAST_AS(object, 1000));
    int cnt = &_end_tester - &_start_tester;

    kprint("\n\n------------ Self-Test -----------\n"
           " %d Test will be executed\n"
           " These tests are expected be done\n"
           " within \033[91m1000\033[0m ticks\n"
           "==================================\n",
           cnt);

    for (round = 0; round < ROUND_EXP; round++)
    {
        u64 start = 1;
        u64 stop = 1;

        start = get_tick_count();
        start_ttimer(&timer);

        kprint("\nstart timer @%lld tick with duration=1000...\n\n", start);
        for (Test t = &_start_tester; t < &_end_tester; t++)
        {
            u64 t1 = get_tick_count();
            int r = t->test_entry(pool);
            u64 t2 = get_tick_count();
            t->passed += r;
            int d = t2 - t1;
            if(t->ticks_min == -1)
            {
                t->ticks_min = d;
                t->ticks_max = d;
                t->ticks_tot = d;
            }
            else
            {
                if(t->ticks_min > d) t->ticks_min = d;
                if(t->ticks_max < d) t->ticks_max = d;
                t->ticks_tot += d;
            }
        }

        stop_ttimer(&timer);
        stop = get_tick_count();

        int tick = stop - start;

        kprint("\nstop timer @%lld tick\n", stop);
        kprint("Test done within %d ticks, Total Tests: %d\n\n", tick, cnt);
        kprint("Round[%-03d] Test done!\n", round);
    }
    report_test();
}

#include"shell.h"
DEFINE_STATIC_CMD(autotest, "execute auto test")